package com.spring.proxy;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

// 切面类（配置文件xml方式）
@Component
public class AOPXML {

    // 前置（在目标方法之前执行，且在环绕通知之后执行）
    public void beforeMethod(JoinPoint joinPoint){  // JoinPoint 能获取到切入点的一些信息
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Logger --> 前置通知，方法名字："+methodName+" 参数："+ Arrays.toString(args));
    }

    // 后置（在目标方法之后执行，且在返回通知之后执行）
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Logger --> 后置通知，方法名字："+methodName);
    }

    // 返回（在目标方法之后执行拿到返回值，returning = "re" 可以得到方法的返回值）
    public void afterReturningMethod(JoinPoint joinPoint,Object re){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Logger --> 返回通知，方法名字："+methodName+" ，返回结果："+re);
    }

    // 异常（目标方法出现异常，这个通知执行，throwing = "ex" 可以得到方法的异常信息）
    public void afterThrowingMethod(JoinPoint joinPoint,Throwable ex){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Logger --> 异常通知，方法名字："+methodName+" ，异常信息："+ex);
    }

    // 环绕（最最先和最最后执行）
    public Object around(ProceedingJoinPoint joinPoint){ // joinPoint的子类，比父类方法更多
        Object result = null;
        try {
            System.out.println("环绕通知==目标方法之前执行");
            result = joinPoint.proceed(); // 调用目标方法
            System.out.println("环绕通知==目标方法之后执行");
        } catch (Throwable throwable) {
            throwable.printStackTrace(); // 打印异常信息
            System.out.println("环绕通知==目标方法异常执行");
        } finally {
            System.out.println("环绕通知==目标方法执行完毕执行");
        }
        return result;
    }

}
